#include "../../../server/net/Buffer.h"
#include "../HttpContext.h"
using namespace yhaida;

HttpContext::HttpContext()
    : _state(kExpectRequestLine)
{
}
bool HttpContext::parseRequest(Buffer *buffer, Timestamp receiveTime)
{
    bool ok = true;
    bool hasMore = true;
    while (hasMore)
    {
        // LOG_DEBUG<<_state;
        if (_state == kExpectRequestLine)
        {
            const char *crlf = buffer->findCRLF();
            if (crlf)
            {
                ok = processRequestLine(buffer->peek(), crlf);
                if (ok)
                {
                    _request.setReceiveTime(receiveTime);
                    buffer->retrieveUntil(crlf + 2);
                    _state = kExpectHeaders;
                }
                else
                {
                    hasMore = false;
                }
            }
            else
            {
                hasMore = false;
            }
        }
        else if (_state == kExpectHeaders)
        {
            const char *crlf = buffer->findCRLF();
            if (crlf)
            {
                const char *colon = std::find(buffer->peek(), crlf, ':');
                if (colon != crlf)
                {
                    _request.addHeader(buffer->peek(), colon, crlf);
                }
                else //空行
                {
                    _state = kGotAll;
                    hasMore = false;
                    if (buffer->readableBytes() > 2)
                    {
                        _state = kExpectBody;
                        hasMore = true;
                    }
                }
                buffer->retrieveUntil(crlf + 2);
            }
            else
            {
                hasMore = false;
            }
        }
        else if (_state == kExpectBody)
        {
            // TODO:
            _request.setBody(buffer->retrieveAllAsString());
            _state = kGotAll;
            hasMore = false;
        }
    }
    return ok;
}
bool HttpContext::gotAll() const
{
    return _state == kGotAll;
}
void HttpContext::reset()
{
    _state = kExpectRequestLine;
    HttpRequest dummy;
    _request.swap(dummy);
}
const HttpRequest &HttpContext::request() const
{
    return _request;
}
HttpRequest &HttpContext::request()
{
    return _request;
}
bool HttpContext::processRequestLine(const char *begin, const char *end)
{
    bool succeed = false;
    const char *start = begin;
    const char *space = std::find(start, end, ' ');
    if (space != end && _request.setMethod(start, space))
    {
        start = space + 1;
        space = std::find(start, end, ' ');
        if (space != end)
        {
            //通过？来带参数，连接域名和参数。
            const char *question = std::find(start, space, '?');
            if (question != space)
            {
                _request.setPath(start, question);
                _request.setQuery(question, space);
            }
            else
            {
                _request.setPath(start, space);
            }
            start = space + 1;
            if (end - start == 8 && std::equal(start, end - 1, "HTTP/1."))
            {
                succeed = true;
            }
            else
            {
                succeed = false;
            }
            if (succeed)
            {
                if (*(end - 1) == '1')
                {
                    _request.setVersion(HttpRequest::kHttp11);
                }
                else if (*(end - 1) == '0')
                {
                    _request.setVersion(HttpRequest::kHttp10);
                }
                else
                {
                    succeed = false;
                }
            }
        }
    }
    return succeed;
}